package cn.ms.neural.moduler.extension.blackwhite.core;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.ms.neural.common.exception.blackwhite.BlackWhiteListException;
import cn.ms.neural.common.exception.blackwhite.black.BlackListException;
import cn.ms.neural.common.exception.blackwhite.white.WhiteListException;
import cn.ms.neural.common.logger.ILogger;
import cn.ms.neural.common.logger.LoggerManager;
import cn.ms.neural.moduler.Moduler;
import cn.ms.neural.moduler.extension.blackwhite.IBlackWhite;
import cn.ms.neural.moduler.extension.blackwhite.conf.BlackWhiteConf;
import cn.ms.neural.moduler.extension.blackwhite.entity.BlackWhiteEntity;
import cn.ms.neural.moduler.extension.blackwhite.support.IBlackWhiteProcessor;

/**
 * 黑白名单 <br>
 * 1.IP黑名单/白名单 2.服务黑名单/白名单 <br>
 * 
 * @author lry
 *
 * @param <REQ>
 * @param <RES>
 */
public class BlackWhiteFactory<REQ, RES> implements IBlackWhite<REQ, RES> {

	private static final ILogger bizDefaultLog = LoggerManager.getBizDefaultLog();
	
	private BlackWhiteConf blackWhiteConf;
	/**
	 * 模块中心
	 */
	private Moduler<REQ, RES> moduler;
	
	/**
	 * 黑白名单清单
	 */
	private Map<String, BlackWhiteEntity[]> blackWhiteListMap;

	@Override
	public void inject(BlackWhiteConf blackWhiteConf, Map<String, BlackWhiteEntity[]> blackWhiteListMap) {
		this.blackWhiteConf = blackWhiteConf;
		if (blackWhiteConf.isBlackwhiteSwitch()) {// 开关打开则校验
			if (blackWhiteListMap == null || blackWhiteListMap.isEmpty()) {
				throw new BlackWhiteListException("黑白名单不能为空");
			}
			for (Map.Entry<String, BlackWhiteEntity[]> entry : blackWhiteListMap.entrySet()) {
				BlackWhiteEntity[] blackWhiteListArray = entry.getValue();
				if (blackWhiteListArray == null || blackWhiteListArray.length < 1) {
					throw new BlackWhiteListException(String.format("黑/白名单[%s]没有设置规则", entry.getKey()));
				}
			}
			this.blackWhiteListMap = blackWhiteListMap;
		}
	}
	
	@Override
	public void setModuler(Moduler<REQ, RES> moduler) {
		this.moduler=moduler;
	}

	@Override
	public void init() throws Throwable {
		
	}

	@Override
	public RES blackwhite(REQ blackWhiteREQ, Map<String, Object> blackWhiteIdKeyVals, IBlackWhiteProcessor<REQ, RES> blackWhiteProcessor, Object... args) throws Throwable {
		if (!blackWhiteConf.isBlackwhiteSwitch()) {// 开关未打开,则直接跳过
			if(blackWhiteConf.isDisableRecordSwitch()){//记录禁用
				if (bizDefaultLog.isWarnEnabled()) {
					bizDefaultLog.warn("黑白名单总开关被禁用了");
				}
			}
			
			return blackWhiteProcessor.processor(blackWhiteREQ);
		}
		
		for (Map.Entry<String, Object> entry:blackWhiteIdKeyVals.entrySet()) {//实时遍历过滤key-value
			BlackWhiteEntity[] blackWhiteListArray = blackWhiteListMap.get(entry.getKey());
			for (BlackWhiteEntity blackWhiteList : blackWhiteListArray) {// 黑白名单遍历
				if (!blackWhiteList.isEnabled()) {// 校验开关
					if (bizDefaultLog.isWarnEnabled()) {
						bizDefaultLog.warn(String.format("[%s]黑白名单的子开关被禁用了", entry.getKey()));
					}
					continue;
				}

				List<String> allowedIps = blackWhiteList.getData();
				switch (blackWhiteList.getBlackWhiteType()) {
				case BLACK: {// 黑名单
					if(blackWhiteConf.isVisitRecordSwitch()){//记录访问清单
						if (bizDefaultLog.isInfoEnabled()) {
							bizDefaultLog.info("[%s]黑名单的访问ID为[%s]", entry.getKey(), entry.getValue());
						}	
					}
					if (allowedIps.contains(String.valueOf(entry.getValue()))) {//[匹配一]全匹配
						String refusedMsg=String.format("[%s]黑名单拒绝ID为[%s]", entry.getKey(), entry.getValue());
						if (bizDefaultLog.isDebugEnabled()) {
							bizDefaultLog.debug(refusedMsg);
						}
						throw new BlackListException(refusedMsg);
					}
					
					for (String allowedIp:allowedIps) {//[匹配二]正则匹配
						Pattern pattern=Pattern.compile(allowedIp);
						Matcher matcher=pattern.matcher(String.valueOf(entry.getValue()));
						if (matcher.find()) {
							String refusedMsg=String.format("[%s]黑名单拒绝ID为[%s]", entry.getKey(), entry.getValue());
							if (bizDefaultLog.isDebugEnabled()) {
								bizDefaultLog.debug(refusedMsg);
							}
							throw new BlackListException(refusedMsg);
						}
					}
					
					break;
				}
				case WHITE: {// 白名单
					if(blackWhiteConf.isVisitRecordSwitch()){//记录访问清单
						if (bizDefaultLog.isInfoEnabled()) {
							bizDefaultLog.info("[%s]白名单的访问ID为[%s]", entry.getKey(), String.valueOf(entry.getValue()));
						}	
					}
					if (allowedIps.contains(String.valueOf(entry.getValue()))) {//[匹配一]全匹配
						break;
					}
					for (String allowedIp:allowedIps) {//[匹配二]正则匹配
						Pattern pattern=Pattern.compile(allowedIp);
						Matcher matcher=pattern.matcher(String.valueOf(entry.getValue()));
						if (matcher.find()) {
							break;
						}
					}
					
					//非白名单,则拒绝请求
					String refusedMsg=String.format("[%s]白名单拒绝ID为[%s]", entry.getKey(), entry.getValue());
					if (bizDefaultLog.isDebugEnabled()) {
						bizDefaultLog.debug(refusedMsg);
					}
					throw new WhiteListException(refusedMsg);
				}
				default:
					throw new BlackWhiteListException("非法过滤类型");
				}
			}
		}

		return blackWhiteProcessor.processor(blackWhiteREQ);
	}

	@Override
	public void destory() throws Throwable {
		// TODO Auto-generated method stub
		
	}

}
